use {
    alloy::primitives::U256,
    tron,
    commons::error,
    repository::model::dapp_transaction::{DAppTransaction, TransactionStatus},
    sqlx::{MySql, Pool},
    std::str::FromStr,
    tracing::info,
};

#[derive(serde::Serialize)]
#[serde(rename_all = "camelCase")]
struct RechargeRequest {
    pub contract: String,
    pub from_addr: String,
    pub to_addr: String,
    pub hash: String,
    pub time_stamp: String,
    pub num: String,
    pub decimals: u8,
}

impl RechargeRequest {
    fn from(transaction: DAppTransaction) -> Self {
        RechargeRequest {
            contract: transaction.contract,
            from_addr: transaction.from_addr,
            to_addr: transaction.recharge_addr,
            hash: transaction.recharge_hash,
            time_stamp: transaction.time_stamp,
            num: transaction.num,
            decimals: transaction.decimals,
        }
    }

    fn recharge_url() -> &'static str {
        "http://127.0.0.1:8080/recharge"
    }
}

pub async fn recharge_remote(
    env: &str,
    chain: &str,
    pool: &Pool<MySql>,
    transaction: &DAppTransaction,
) -> anyhow::Result<()> {
    DAppTransaction::update_status(
        pool,
        transaction.id.unwrap(),
        u8::from(TransactionStatus::RechargeProcessing),
    )
    .await;
    let contract = transaction.contract.clone();
    let recharge_addr = transaction.recharge_addr.clone();
    let num_str = transaction.num.clone();
    let num_str = num_str.as_str();
    let balance_str = match chain {
        "TRON" => {
            let client = tron::base::client::build_client(env);
            tron::service::token::token_balance(&client, &contract, &recharge_addr).await?
        }
        _ => "0".to_string(),
    };
    let num_u256 = U256::from_str(num_str)?;
    let bal_u256 = U256::from_str(&balance_str)?;
    if bal_u256 < num_u256 {
        let tf = error::TransferError::NotSufficientFunds {
            account: recharge_addr,
            balance: balance_str,
            hash: transaction.recharge_hash.clone(),
            number: num_str.to_string(),
        };
        return Err(tf.into());
    }

    /*
     * todo
    let request = RechargeRequest::from((*transaction).clone());
    let remote_client = reqwest::Client::new();
    let resp = remote_client
        .post(RechargeRequest::recharge_url())
        .json(&request)
        .send()
        .await
        .unwrap();
    if resp.status().is_success() {
    */

    if true {
        DAppTransaction::update_status(
            pool,
            transaction.id.unwrap(),
            u8::from(TransactionStatus::RechargeSuccess),
        )
        .await;
    } else {
        DAppTransaction::update_status(
            pool,
            transaction.id.unwrap(),
            u8::from(TransactionStatus::Unprocessed),
        )
        .await;
    }

    Ok(())
}
